﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Testtt
{
    public partial class Form1 : Form
    {
        private Point m_StartLocation;
        private Block m_currentBlock;
        private Block m_nextBlock;
        private bool m_stillRuning = false;
        private int m_score = 0;
        public Form1()
        {
            InitializeComponent();
        }

        public void InitGameSpace()
        {
            GameSpace.MinBlockWidth = 30;
            GameSpace.Width = this.panelMain.Width / GameSpace.MinBlockWidth;
            GameSpace.Height = this.panelMain.Height / GameSpace.MinBlockWidth;
            GameSpace.ArriveBlock = new Square[Width, Height];
            GameSpace.ArrBitBlock = new int[Height];
            GameSpace.Backbround = Color.Black;
            GameSpace.WinHandle = this.panelMain.Handle;
            GameSpace.HasGrid = true;
            GameSpace.GridColor = Color.White;
            GameSpace.BlockColor = new Color[] { Color.LightCyan, Color.DarkSeaGreen, Color.Beige, Color.Beige, Color.Beige, Color.Beige, Color.Beige };
            GameSpace.BlockFore = new Color[] { Color.Blue, Color.Beige, Color.DarkKhaki, Color.DarkMagenta, Color.DarkOliveGreen, Color.DarkOrange, Color.DarkRed };
            this.panelMain.BackColor = GameSpace.Backbround;
            this.pictureBox1.BackColor = GameSpace.Backbround;
            m_StartLocation = new Point((GameSpace.MinBlockWidth * 5) - 60, 0);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            InitGameSpace();
            timer1.Interval = (int)Speeds.slower;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (!m_stillRuning)
                return;

            if (!m_currentBlock.Down())
            {
                if (m_currentBlock.Top() == 0)
                {
                    m_stillRuning = false;
                    timer1.Stop();
                    return;
                }
                int eraseLines = GameSpace.CheckLines();
                if (eraseLines > 0)
                {
                    m_score += GameSpace.Width * eraseLines;

                    panelMain.Invalidate();
                    Application.DoEvents();
                    GameSpace.Redraw();
                }
                m_currentBlock = new Block(m_StartLocation, m_nextBlock.Blocktype);
                m_currentBlock.Draw(GameSpace.WinHandle);
                this.pictureBox1.Refresh();
                m_nextBlock = new Block(new Point(30, 10), BlockType.undefined);
                m_nextBlock.Draw(pictureBox1.Handle);
            }
            m_currentBlock.Down();
        }
        private void Form1_Activated(object sender, EventArgs e)
        {
            this.panelMain.Invalidate();
            Application.DoEvents();
            GameSpace.Redraw();
        }
        protected override bool ProcessCmdKey(ref   Message msg, Keys keyData)
        {
            switch (keyData)
            {
                case Keys.Right: m_currentBlock.Right(); break;
                case Keys.Left: m_currentBlock.Left(); break;
                case Keys.Up: m_currentBlock.Rotate(); break;
                case Keys.Down: while (m_currentBlock.Down())
                    {
                        if (this.m_currentBlock.Squares[2].Location.Y == (GameSpace.Height - 1) * GameSpace.MinBlockWidth)
                        {
                            m_currentBlock = new Block(m_StartLocation, m_nextBlock.Blocktype);
                            m_currentBlock.Draw(GameSpace.WinHandle);
                            this.pictureBox1.Refresh();
                            m_nextBlock = new Block(new Point(50, 10), BlockType.undefined);
                            m_nextBlock.Draw(pictureBox1.Handle);
                            break;
                        }
                    };
                    break;
                case Keys.Space:
                    timer1.Enabled = !timer1.Enabled;
                    break;
                case Keys.Enter:
                    BeginGame();
                    break;
            }
            panelMain.Focus();
            return false;
        }

        private void BeginGame()
        {
            timer1.Enabled = true;
            if (GameSpace.HasGrid)
            {
                System.Drawing.Pen myPen = new System.Drawing.Pen(System.Drawing.Color.White);
                Graphics _p = this.panelMain.CreateGraphics();
                for (int y = Height - 1; y >= 1; y--)
                {
                    _p.DrawLine(myPen, new Point(0, y * GameSpace.MinBlockWidth), new Point((Width - 1) * GameSpace.MinBlockWidth, y * GameSpace.MinBlockWidth));
                }
                for (int x = 1; x < Width; x++)
                {
                    _p.DrawLine(myPen, new Point(x * GameSpace.MinBlockWidth, 0), new Point(x * GameSpace.MinBlockWidth, (Height - 1) * GameSpace.MinBlockWidth));
                }
            }
            if (m_currentBlock == null)
            {
                m_currentBlock = new Block(m_StartLocation, BlockType.undefined);
                m_currentBlock.Draw(GameSpace.WinHandle);
                m_nextBlock = new Block(new Point(30, 0), BlockType.undefined);
                m_nextBlock.Draw(pictureBox1.Handle);
                m_currentBlock.Down();
                m_stillRuning = true;
                timer1.Start();
            }
        }
        private enum Speeds
        {
            slower = 1000,
            slow = 800,
            quick = 500,
            quicker = 350,
            quickest = 250
        };

        private void button1_Click(object sender, EventArgs e)
        {
            BeginGame();
        }
    }

    public class Block
    {
        public BlockType Blocktype { get; set; }
        public Point Location { get; set; }
        public Size BlockSize { get; set; }
        public Color BackColor { get; set; }
        public Color ForeColor { get; set; }
        public RotateDirections myRotation { get; set; }

        public Square[] Squares { get; set; }
        public Size SquareSize { get; set; }
        public Block(Point thisLocation, BlockType bType)
        {
            Random _rand = new Random();
            int _iSeed = _rand.Next(GameSpace.BlockColor.Length);
            this.BackColor = GameSpace.BlockColor[_iSeed];
            this.ForeColor = GameSpace.BlockColor[_iSeed];

            this.Location = thisLocation;

            if (bType == BlockType.undefined)
            {
                _rand = new Random();
                Blocktype = (BlockType)(_rand.Next(7) + 1);
            }
            else
                Blocktype = bType;

            SquareSize = new Size(GameSpace.MinBlockWidth, GameSpace.MinBlockWidth);
            Squares = New4Square(this.Blocktype);
        }
        public Block(Point thisLocation, BlockType bType, Color fc, Color bc)
        {
            if (bType == BlockType.undefined)
            {
                Random _rand = new Random();
                Blocktype = (BlockType)(_rand.Next(7) + 1);
            }
            else
                Blocktype = bType;

            this.BackColor = bc;
            this.ForeColor = fc;

            this.Location = thisLocation;
            SquareSize = new Size(GameSpace.MinBlockWidth, GameSpace.MinBlockWidth);
            Squares = New4Square(this.Blocktype);
        }
        public void Draw(System.IntPtr winHandle)
        {
            foreach (Square _point in Squares)
            {
                _point.Draw(winHandle);
            }
        }
        public void Erase(System.IntPtr winHandle)
        {
            foreach (Square _point in Squares)
            {
                _point.Erase(winHandle);
            }
        }

        private Square[] New4Square(BlockType type)
        {
            #region
            Square _squares1 = new Square(this.SquareSize, this.ForeColor, this.BackColor);
            Square _squares2 = new Square(this.SquareSize, this.ForeColor, this.BackColor);
            Square _squares3 = new Square(this.SquareSize, this.ForeColor, this.BackColor);
            Square _squares4 = new Square(this.SquareSize, this.ForeColor, this.BackColor);
            if (this.Blocktype == BlockType.I)
            {
                _squares1.Location = new Point(this.Location.X, this.Location.Y);
                _squares2.Location = new Point(this.Location.X + GameSpace.MinBlockWidth, this.Location.Y);
                _squares3.Location = new Point(this.Location.X + 2 * GameSpace.MinBlockWidth, this.Location.Y);
                _squares4.Location = new Point(this.Location.X + 3 * GameSpace.MinBlockWidth, this.Location.Y);
            }
            else if (this.Blocktype == BlockType.L1)
            {
                _squares1.Location = new Point(this.Location.X, this.Location.Y);
                _squares2.Location = new Point(this.Location.X + GameSpace.MinBlockWidth, this.Location.Y);
                _squares3.Location = new Point(this.Location.X + 2 * GameSpace.MinBlockWidth, this.Location.Y);
                _squares4.Location = new Point(this.Location.X, this.Location.Y + GameSpace.MinBlockWidth);
            }
            else if (this.Blocktype == BlockType.L2)
            {
                _squares1.Location = new Point(this.Location.X, this.Location.Y);
                _squares2.Location = new Point(this.Location.X + GameSpace.MinBlockWidth, this.Location.Y);
                _squares3.Location = new Point(this.Location.X + 2 * GameSpace.MinBlockWidth, this.Location.Y);
                _squares4.Location = new Point(this.Location.X + 2 * GameSpace.MinBlockWidth, this.Location.Y + GameSpace.MinBlockWidth);
            }
            else if (this.Blocktype == BlockType.O)
            {
                _squares1.Location = new Point(this.Location.X, this.Location.Y);
                _squares2.Location = new Point(this.Location.X + GameSpace.MinBlockWidth, this.Location.Y);
                _squares3.Location = new Point(this.Location.X, this.Location.Y + GameSpace.MinBlockWidth);
                _squares4.Location = new Point(this.Location.X + GameSpace.MinBlockWidth, this.Location.Y + GameSpace.MinBlockWidth);
            }
            else if (this.Blocktype == BlockType.Z1)
            {
                _squares1.Location = new Point(this.Location.X, this.Location.Y);
                _squares2.Location = new Point(this.Location.X + GameSpace.MinBlockWidth, this.Location.Y);
                _squares3.Location = new Point(this.Location.X + GameSpace.MinBlockWidth, this.Location.Y + GameSpace.MinBlockWidth);
                _squares4.Location = new Point(this.Location.X + 2 * GameSpace.MinBlockWidth, this.Location.Y + GameSpace.MinBlockWidth);
            }
            else if (this.Blocktype == BlockType.Z2)
            {
                _squares1.Location = new Point(this.Location.X, this.Location.Y + GameSpace.MinBlockWidth);
                _squares2.Location = new Point(this.Location.X + GameSpace.MinBlockWidth, this.Location.Y + GameSpace.MinBlockWidth);
                _squares3.Location = new Point(this.Location.X + GameSpace.MinBlockWidth, this.Location.Y);
                _squares4.Location = new Point(this.Location.X + 2 * GameSpace.MinBlockWidth, this.Location.Y);
            }
            else if (this.Blocktype == BlockType.T)
            {
                _squares1.Location = new Point(this.Location.X, this.Location.Y);
                _squares2.Location = new Point(this.Location.X + GameSpace.MinBlockWidth, this.Location.Y);
                _squares3.Location = new Point(this.Location.X + 2 * GameSpace.MinBlockWidth, this.Location.Y);
                _squares4.Location = new Point(this.Location.X + GameSpace.MinBlockWidth, this.Location.Y + GameSpace.MinBlockWidth);
            }
            #endregion

            return new Square[] { _squares1, _squares2, _squares3, _squares4 };
        }

        public bool Down()
        {
            if (GameSpace.IsEmpty(Squares[0].Location.X / GameSpace.MinBlockWidth, Squares[0].Location.Y / GameSpace.MinBlockWidth + 1) &&
                GameSpace.IsEmpty(Squares[1].Location.X / GameSpace.MinBlockWidth, Squares[1].Location.Y / GameSpace.MinBlockWidth + 1) &&
                GameSpace.IsEmpty(Squares[2].Location.X / GameSpace.MinBlockWidth, Squares[2].Location.Y / GameSpace.MinBlockWidth + 1) &&
                GameSpace.IsEmpty(Squares[3].Location.X / GameSpace.MinBlockWidth, Squares[3].Location.Y / GameSpace.MinBlockWidth + 1))
            {
                Erase(GameSpace.WinHandle);
                Squares[0].Location = new Point(Squares[0].Location.X, Squares[0].Location.Y + GameSpace.MinBlockWidth);
                Squares[1].Location = new Point(Squares[1].Location.X, Squares[1].Location.Y + GameSpace.MinBlockWidth);
                Squares[2].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y + GameSpace.MinBlockWidth);
                Squares[3].Location = new Point(Squares[3].Location.X, Squares[3].Location.Y + GameSpace.MinBlockWidth);
                Draw(GameSpace.WinHandle);
                return true;
            }
            else
            {
                GameSpace.StopSquare(Squares[0], Squares[0].Location.X / GameSpace.MinBlockWidth, Squares[0].Location.Y / GameSpace.MinBlockWidth);
                GameSpace.StopSquare(Squares[1], Squares[1].Location.X / GameSpace.MinBlockWidth, Squares[1].Location.Y / GameSpace.MinBlockWidth);
                GameSpace.StopSquare(Squares[2], Squares[2].Location.X / GameSpace.MinBlockWidth, Squares[2].Location.Y / GameSpace.MinBlockWidth);
                GameSpace.StopSquare(Squares[3], Squares[3].Location.X / GameSpace.MinBlockWidth, Squares[3].Location.Y / GameSpace.MinBlockWidth);
                return false;
            }
        }
        public bool Left()
        {
            if (GameSpace.IsEmpty(Squares[0].Location.X / GameSpace.MinBlockWidth - 1, Squares[0].Location.Y / GameSpace.MinBlockWidth) &&
                GameSpace.IsEmpty(Squares[1].Location.X / GameSpace.MinBlockWidth - 1, Squares[1].Location.Y / GameSpace.MinBlockWidth) &&
                GameSpace.IsEmpty(Squares[2].Location.X / GameSpace.MinBlockWidth - 1, Squares[2].Location.Y / GameSpace.MinBlockWidth) &&
                GameSpace.IsEmpty(Squares[3].Location.X / GameSpace.MinBlockWidth - 1, Squares[3].Location.Y / GameSpace.MinBlockWidth))
            {
                Erase(GameSpace.WinHandle);
                Squares[0].Location = new Point(Squares[0].Location.X - GameSpace.MinBlockWidth, Squares[0].Location.Y);
                Squares[1].Location = new Point(Squares[1].Location.X - GameSpace.MinBlockWidth, Squares[1].Location.Y);
                Squares[2].Location = new Point(Squares[2].Location.X - GameSpace.MinBlockWidth, Squares[2].Location.Y);
                Squares[3].Location = new Point(Squares[3].Location.X - GameSpace.MinBlockWidth, Squares[3].Location.Y);
                Draw(GameSpace.WinHandle);
                return true;
            }
            else
            {
                return false;
            }
        }
        public bool Right()
        {
            if (GameSpace.IsEmpty(Squares[0].Location.X / GameSpace.MinBlockWidth + 1, Squares[0].Location.Y / GameSpace.MinBlockWidth) &&
                GameSpace.IsEmpty(Squares[1].Location.X / GameSpace.MinBlockWidth + 1, Squares[1].Location.Y / GameSpace.MinBlockWidth) &&
                GameSpace.IsEmpty(Squares[2].Location.X / GameSpace.MinBlockWidth + 1, Squares[2].Location.Y / GameSpace.MinBlockWidth) &&
                GameSpace.IsEmpty(Squares[3].Location.X / GameSpace.MinBlockWidth + 1, Squares[3].Location.Y / GameSpace.MinBlockWidth))
            {
                Erase(GameSpace.WinHandle);
                Squares[0].Location = new Point(Squares[0].Location.X + GameSpace.MinBlockWidth, Squares[0].Location.Y);
                Squares[1].Location = new Point(Squares[1].Location.X + GameSpace.MinBlockWidth, Squares[1].Location.Y);
                Squares[2].Location = new Point(Squares[2].Location.X + GameSpace.MinBlockWidth, Squares[2].Location.Y);
                Squares[3].Location = new Point(Squares[3].Location.X + GameSpace.MinBlockWidth, Squares[3].Location.Y);
                Draw(GameSpace.WinHandle);
                return true;
            }
            else
            {
                return false;
            }
        }
        public void Rotate()
        {
            Point oldPosition1 = Squares[0].Location;
            Point oldPosition2 = Squares[1].Location;
            Point oldPosition3 = Squares[2].Location;
            Point oldPosition4 = Squares[3].Location;
            RotateDirections oldRotation = myRotation;

            Erase(GameSpace.WinHandle);
            switch (this.Blocktype)
            {
                case BlockType.O:
                    break;
                case BlockType.I:
                    switch (myRotation)
                    {
                        case RotateDirections.North:
                            myRotation = RotateDirections.East;
                            Squares[0].Location = new Point(Squares[1].Location.X - GameSpace.MinBlockWidth, Squares[1].Location.Y);
                            Squares[2].Location = new Point(Squares[1].Location.X + GameSpace.MinBlockWidth, Squares[1].Location.Y);
                            Squares[3].Location = new Point(Squares[1].Location.X + 2 * GameSpace.MinBlockWidth, Squares[1].Location.Y);
                            break;
                        case RotateDirections.East:
                            myRotation = RotateDirections.North;
                            Squares[0].Location = new Point(Squares[1].Location.X, Squares[1].Location.Y - GameSpace.MinBlockWidth);
                            Squares[2].Location = new Point(Squares[1].Location.X, Squares[1].Location.Y + GameSpace.MinBlockWidth);
                            Squares[3].Location = new Point(Squares[1].Location.X, Squares[1].Location.Y + 2 * GameSpace.MinBlockWidth);
                            break;
                    }
                    break;
                case BlockType.L2:
                    switch (myRotation)
                    {
                        case RotateDirections.North:
                            myRotation = RotateDirections.East;
                            Squares[0].Location = new Point(Squares[2].Location.X + 2 * GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            Squares[1].Location = new Point(Squares[2].Location.X + GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            Squares[3].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y - GameSpace.MinBlockWidth);
                            break;
                        case RotateDirections.East:
                            myRotation = RotateDirections.South;
                            Squares[0].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y + 2 * GameSpace.MinBlockWidth);
                            Squares[1].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y + GameSpace.MinBlockWidth);
                            Squares[3].Location = new Point(Squares[2].Location.X + GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            break;
                        case RotateDirections.South:
                            myRotation = RotateDirections.West;
                            Squares[0].Location = new Point(Squares[2].Location.X - 2 * GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            Squares[1].Location = new Point(Squares[2].Location.X - GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            Squares[3].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y + GameSpace.MinBlockWidth);
                            break;
                        case RotateDirections.West:
                            myRotation = RotateDirections.North;
                            Squares[0].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y - 2 * GameSpace.MinBlockWidth);
                            Squares[1].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y - GameSpace.MinBlockWidth);
                            Squares[3].Location = new Point(Squares[2].Location.X - GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            break;
                    }
                    break;
                case BlockType.L1:
                    //L形方块有四种旋转方向
                    switch (myRotation)
                    {
                        case RotateDirections.North:
                            myRotation = RotateDirections.East;
                            Squares[0].Location = new Point(Squares[2].Location.X + 2 * GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            Squares[1].Location = new Point(Squares[2].Location.X + GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            Squares[3].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y + GameSpace.MinBlockWidth);
                            break;
                        case RotateDirections.East:
                            myRotation = RotateDirections.South;
                            Squares[0].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y + 2 * GameSpace.MinBlockWidth);
                            Squares[1].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y + GameSpace.MinBlockWidth);
                            Squares[3].Location = new Point(Squares[2].Location.X - GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            break;
                        case RotateDirections.South:
                            myRotation = RotateDirections.West;
                            Squares[0].Location = new Point(Squares[2].Location.X - 2 * GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            Squares[1].Location = new Point(Squares[2].Location.X - GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            Squares[3].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y - GameSpace.MinBlockWidth);
                            break;
                        case RotateDirections.West:
                            myRotation = RotateDirections.North;
                            Squares[0].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y - 2 * GameSpace.MinBlockWidth);
                            Squares[1].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y - GameSpace.MinBlockWidth);
                            Squares[3].Location = new Point(Squares[2].Location.X + GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            break;
                    }
                    break;
                case BlockType.T:
                    //T形方块也有四种旋转方向
                    switch (myRotation)
                    {
                        case RotateDirections.North:
                            myRotation = RotateDirections.East;
                            Squares[0].Location = new Point(Squares[1].Location.X, Squares[1].Location.Y - GameSpace.MinBlockWidth);
                            Squares[2].Location = new Point(Squares[1].Location.X, Squares[1].Location.Y + GameSpace.MinBlockWidth);
                            Squares[3].Location = new Point(Squares[1].Location.X - GameSpace.MinBlockWidth, Squares[1].Location.Y);
                            break;
                        case RotateDirections.East:
                            myRotation = RotateDirections.South;
                            Squares[0].Location = new Point(Squares[1].Location.X + GameSpace.MinBlockWidth, Squares[1].Location.Y);
                            Squares[2].Location = new Point(Squares[1].Location.X - GameSpace.MinBlockWidth, Squares[1].Location.Y);
                            Squares[3].Location = new Point(Squares[1].Location.X, Squares[1].Location.Y - GameSpace.MinBlockWidth);
                            break;
                        case RotateDirections.South:
                            myRotation = RotateDirections.West;
                            Squares[0].Location = new Point(Squares[1].Location.X, Squares[1].Location.Y + GameSpace.MinBlockWidth);
                            Squares[2].Location = new Point(Squares[1].Location.X, Squares[1].Location.Y - GameSpace.MinBlockWidth);
                            Squares[3].Location = new Point(Squares[1].Location.X + GameSpace.MinBlockWidth, Squares[1].Location.Y);
                            break;
                        case RotateDirections.West:
                            myRotation = RotateDirections.North;
                            Squares[0].Location = new Point(Squares[1].Location.X - GameSpace.MinBlockWidth, Squares[1].Location.Y);
                            Squares[2].Location = new Point(Squares[1].Location.X + GameSpace.MinBlockWidth, Squares[1].Location.Y);
                            Squares[3].Location = new Point(Squares[1].Location.X, Squares[1].Location.Y + GameSpace.MinBlockWidth);
                            break;
                    }
                    break;
                case BlockType.Z1:
                    //Z形方块有两种旋转方向
                    switch (myRotation)
                    {
                        case RotateDirections.North:
                            myRotation = RotateDirections.East;
                            Squares[0].Location = new Point(Squares[1].Location.X, Squares[1].Location.Y - GameSpace.MinBlockWidth);
                            Squares[2].Location = new Point(Squares[1].Location.X - GameSpace.MinBlockWidth, Squares[1].Location.Y);
                            Squares[3].Location = new Point(Squares[1].Location.X - GameSpace.MinBlockWidth, Squares[1].Location.Y + GameSpace.MinBlockWidth);
                            break;
                        case RotateDirections.East:
                            myRotation = RotateDirections.North;
                            Squares[0].Location = new Point(Squares[1].Location.X - GameSpace.MinBlockWidth, Squares[1].Location.Y);
                            Squares[2].Location = new Point(Squares[1].Location.X, Squares[1].Location.Y + GameSpace.MinBlockWidth);
                            Squares[3].Location = new Point(Squares[1].Location.X + GameSpace.MinBlockWidth, Squares[1].Location.Y + GameSpace.MinBlockWidth);
                            break;
                    }
                    break;
                case BlockType.Z2:
                    //S形方块有两种旋转方向
                    switch (myRotation)
                    {
                        case RotateDirections.North:
                            myRotation = RotateDirections.East;
                            Squares[0].Location = new Point(Squares[2].Location.X + GameSpace.MinBlockWidth, Squares[2].Location.Y + GameSpace.MinBlockWidth);
                            Squares[1].Location = new Point(Squares[2].Location.X + GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            Squares[3].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y - GameSpace.MinBlockWidth);
                            break;
                        case RotateDirections.East:
                            myRotation = RotateDirections.North;
                            Squares[0].Location = new Point(Squares[2].Location.X - GameSpace.MinBlockWidth, Squares[2].Location.Y + GameSpace.MinBlockWidth);
                            Squares[1].Location = new Point(Squares[2].Location.X, Squares[2].Location.Y + GameSpace.MinBlockWidth);
                            Squares[3].Location = new Point(Squares[2].Location.X + GameSpace.MinBlockWidth, Squares[2].Location.Y);
                            break;
                    }
                    break;
            }
            if (!(GameSpace.IsEmpty(Squares[0].Location.X / GameSpace.MinBlockWidth, Squares[0].Location.Y / GameSpace.MinBlockWidth) &&
                GameSpace.IsEmpty(Squares[1].Location.X / GameSpace.MinBlockWidth, Squares[1].Location.Y / GameSpace.MinBlockWidth) &&
                GameSpace.IsEmpty(Squares[2].Location.X / GameSpace.MinBlockWidth, Squares[2].Location.Y / GameSpace.MinBlockWidth) &&
                GameSpace.IsEmpty(Squares[3].Location.X / GameSpace.MinBlockWidth, Squares[3].Location.Y / GameSpace.MinBlockWidth)))
            {
                myRotation = oldRotation;
                Squares[0].Location = oldPosition1;
                Squares[1].Location = oldPosition2;
                Squares[2].Location = oldPosition3;
                Squares[3].Location = oldPosition4;
            }
            Draw(GameSpace.WinHandle);
        }
        public int Top()
        {
            return Math.Min(Squares[0].Location.Y, Math.Min(Squares[1].Location.Y, Math.Min(Squares[2].Location.Y, Squares[3].Location.Y)));
        }
    }
    public class Square
    {
        public Point Location;
        public Size size;
        public Color ForeColor;
        public Color BackColor;
        public Square(Size initSize, Color initForeColor, Color initBackColor)
        {
            size = initSize;
            ForeColor = initForeColor;
            BackColor = initBackColor;
        }
        //画方块
        public void Draw(System.IntPtr winHandle)
        {
            Graphics g = Graphics.FromHwnd(winHandle);
            GraphicsPath gp = new GraphicsPath();
            Rectangle rec = new Rectangle(Location, size);
            gp.AddRectangle(rec);

            Color[] surroundColor = new Color[] { BackColor };
            PathGradientBrush pb = new PathGradientBrush(gp);
            pb.CenterColor = ForeColor;
            pb.SurroundColors = surroundColor;
            g.FillPath(pb, gp);
        }
        //擦除方块
        public void Erase(System.IntPtr winHandle)
        {
            Graphics g = Graphics.FromHwnd(winHandle);
            Rectangle rec = new Rectangle(Location, size);
            g.FillRectangle(new SolidBrush(GameSpace.Backbround), rec);
        }
    }

    public class GameSpace
    {
        public static IntPtr WinHandle { get; set; }
        public static int Width { get; set; }
        public static int Height { get; set; }
        public static int[] ArrBitBlock { get; set; }
        private const int BitEmpty = 0x0;      //0000 0000 0000 0000 0000
        private const int BitFull = 0xFFFFF;   //1111 1111 1111 1111 1111
        public static Square[,] ArriveBlock;

        public static Color Backbround { get; set; }
        public static Color GridColor { get; set; }
        public static bool HasGrid { get; set; }

        public static Color[] BlockColor { get; set; }
        public static Color[] BlockFore { get; set; }
        public static int MinBlockWidth { get; set; }

        public static bool IsEmpty(int x, int y)
        {
            if (y < 0 || y >= Height)
                return false;
            if (x < 0 || x >= Width)
                return false;
            if ((ArrBitBlock[y] & (1 << x)) != 0)
                return false;
            else
                return true;
        }
        internal static void Redraw()
        {
            for (int y = Height - 1; y >= 0; y--)
                if (ArrBitBlock[y] != BitEmpty)
                    for (int x = 0; x < Width; x++)
                        if ((ArrBitBlock[y] & (1 << x)) != 0)
                            ArriveBlock[x, y].Draw(WinHandle);
        }
        public static void StopSquare(Square sq, int x, int y)
        {
            ArriveBlock[x, y] = sq;
            ArrBitBlock[y] = ArrBitBlock[y] | (1 << x);
        }
        public static int CheckLines()
        {

            int lineFullCount = 0;
            int y = Height - 1;
            while (y >= 0 && ArrBitBlock[y] != BitEmpty)
            {
                if (ArrBitBlock[y] == BitFull)
                {
                    lineFullCount++;
                    ArrBitBlock[y] = BitEmpty;
                    //PlaySound("FinishOneLine"); 
                    for (int x = 0; x < Width; x++)
                        ArriveBlock[x, y] = null;
                    for (int i = y; i - 1 >= 0; i--)
                    {
                        for (int x = 0; x < Width; x++)
                        {
                            if ((ArrBitBlock[i - 1] & (1 << x)) != 0)
                            {
                                ArriveBlock[x, i - 1].Location = new Point(ArriveBlock[x, i - 1].Location.X, ArriveBlock[x, i - 1].Location.Y + GameSpace.MinBlockWidth);
                                ArriveBlock[x, i] = ArriveBlock[x, i - 1];
                            }
                        }
                        ArrBitBlock[i] = ArrBitBlock[i - 1];
                    }
                }
                else  //当消除一行后指针不下移，当没有消除的时候指针才下移
                    y--;
            }//while循环结束
            return lineFullCount;
        }
    }

    public enum BlockType
    {
        undefined,
        I,
        L1,
        L2,
        Z1,
        Z2,
        T,
        O
    }
    public enum RotateDirections
    {
        North = 1,
        East = 2,
        South = 3,
        West = 4
    }
}
